package edu.utsa.cs.contactmanager.views;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import edu.utsa.cs.contactmanager.Contact;
import edu.utsa.cs.contactmanager.ContactManager;
import edu.utsa.cs.contactmanager.FileDialog;
import edu.utsa.cs.contactmanager.OnTaskCompleted;
import edu.utsa.cs.contactmanager.R;
import edu.utsa.cs.contactmanager.FileDialog.DirectorySelectedListener;
import edu.utsa.cs.contactmanager.FileDialog.FileSelectedListener;
import edu.utsa.cs.contactmanager.R.id;
import edu.utsa.cs.contactmanager.R.layout;
import edu.utsa.cs.contactmanager.R.menu;

public class View_Contacts extends ListActivity implements OnTaskCompleted{
	private List<Contact> contacts;
	private ArrayList<String> names;
	private TreeMap<String, Contact> hm;
	
	/**
	 * Android specific method for when the activity is started. See Android application lifecycle.
	 */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ContactManager.initialize(this);//Important for first run only
        listenForPhone();
        
    }
    
    @Override
    public void onResume(){
    	ContactManager.open();    	
    	resetContactsView();
    	super.onResume();
    };
    
    @Override
    public void onPause(){
    	ContactManager.close();
    	super.onPause();
    }
    
    /**
     * Call this function anytime there's a change to what will be viewed.
     */
    private void resetContactsView(){
    	String n;        
        hm = new TreeMap<String, Contact>();
        
    	names = new ArrayList<String>();
    	this.contacts = ContactManager.getContacts();
        for(Contact c : contacts){
        	n = c.getFirstName() + " " + c.getLastName();
        	names.add(n);
        	hm.put(n, c);
        }
        
        if(contacts.isEmpty())
        	setContentView(R.layout.activity_view_no_contacts);
        else{
        	setContentView(R.layout.activity_view_contacts);
        	setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, names));
        }
        
        Collections.sort(names);
    }
    
    @Override
    protected void onListItemClick(ListView list, View view, int position, long id){
    	super.onListItemClick(list, view, position, id);
    	
    	Contact contact = hm.get(names.get(position));
    	Intent i = new Intent(this, View_SingleContact.class);
    	i.putExtra("contact", contact);
    	startActivity(i);
    	
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	getMenuInflater().inflate(R.menu.view__contacts, menu);    	
    	super.onCreateOptionsMenu(menu);
        
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_add:
        	addContact();
        	return true;
        case R.id.action_search:
        	searchForContact();
            return true;
        case R.id.action_view_groups:
        	showGroups();
        	return true;
        case R.id.action_import:
        	importContactsFromAndroidStockApp();
            return true;
        case R.id.action_import_disk:
        	importContactsFromDisk();
            return true;
        case R.id.action_export_disk:
        	exportContacts();
            return true;
        case R.id.phoneNumbers:
        	about();
        	return true;
        case R.id.action_exit:
            exit();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
    
    /**
     * Add a contact by creating a black contact object and passing it to the view single contact.
     */
    private void addContact(){
    	Contact c = new Contact("First", "Last", "example@example.com", null, false);
    	Intent i = new Intent(this, View_EditSingleContact.class);
    	i.putExtra("contact", c);
    	startActivity(i);
    }
    
    private void searchForContact(){
    	Intent i = new Intent(this, View_Search.class);
    	startActivity(i);
    }
    
    private String fileExtension = "cmexport";
    
    
    /**
     * This function creates a dialog that asks where the user wants to export the database to 
     */
    private void exportContacts(){
    	
    	File mPath = new File(Environment.getExternalStorageDirectory() + "//DIR//");
        FileDialog fileDialog = new FileDialog(this, mPath);
        fileDialog.setSelectDirectoryOption(true);
        fileDialog.addDirectoryListener(new FileDialog.DirectorySelectedListener() {
          public void directorySelected(File directory) {
              Log.d(getClass().getName(), "selected dir " + directory.toString());
              

              try {
                  File sd = Environment.getExternalStorageDirectory();
                  File data = Environment.getDataDirectory();

                  if (sd.canWrite()) {
                      String currentDBPath = "//data//edu.utsa.cs.contactmanager//databases//contactManager";
                      String backupDBPath = directory.toString();
                      File currentDB = new File(data, currentDBPath);
                      File backupDB = new File(backupDBPath, "contactManager." + fileExtension);

                      System.out.println(backupDB.toString());
                      if (currentDB.exists()) {
                          FileChannel src = new FileInputStream(currentDB).getChannel();
                          FileChannel dst = new FileOutputStream(backupDB).getChannel();
                          dst.transferFrom(src, 0, src.size());
                          src.close();
                          dst.close();
                          
                          Context context = getApplicationContext();
                          
                          
                          CharSequence text = "Exported database \"contactManager\" to (" + directory.toString() + ")";
                          int duration = Toast.LENGTH_LONG;

                          Toast toast = Toast.makeText(context, text, duration);
                          toast.show(); 
                      }
                      else{
                          Context context = getApplicationContext();
                          CharSequence text = "Unable to find database, this is probably a programming error.";
                          int duration = Toast.LENGTH_LONG;
    
                          Toast toast = Toast.makeText(context, text, duration);
                          toast.show();
                      }
                  }
                  else{
                      Context context = getApplicationContext();
                      CharSequence text = "Unable to export database \"contactManager\" to (" + directory.toString() + ") due to unwritable file system.";
                      int duration = Toast.LENGTH_LONG;

                      Toast toast = Toast.makeText(context, text, duration);
                      toast.show();
                  }
                  
                  
                  
              } catch (Exception e) {
                  Context context = getApplicationContext();
                  CharSequence text = "ERROR exporting database \"contactManager\" to (" + directory.toString() + ")";
                  int duration = Toast.LENGTH_LONG;

                  Toast toast = Toast.makeText(context, text, duration);
                  toast.show();
                  
              }
          //http://stackoverflow.com/questions/1995320/how-to-backup-database-file-to-sdcard-on-android

          }
        });
        fileDialog.showDialog();
        
    }
    
    /**
     * This function creates a dialog to choose where to import the contacts from
     */
    private void importContactsFromDisk(){
        
    	final OnTaskCompleted callback = this;
    	
        File mPath = new File(Environment.getExternalStorageDirectory() + "//DIR//");
        FileDialog fileDialog = new FileDialog(this, mPath);
        //fileDialog.setFileEndsWith(fileExtension);
        fileDialog.addFileListener(new FileDialog.FileSelectedListener() {
            public void fileSelected(File file) {
                Log.d(getClass().getName(), "selected file " + file.toString());

                
                Context context = getApplicationContext();
                CharSequence text = "Loading database from: " + file.toString();
                int duration = Toast.LENGTH_LONG;

                Toast toast = Toast.makeText(context, text, duration);
                toast.show();
                
                ContactManager.importFromFile(getApplicationContext(), file.toString());
                callback.onTaskComplete();
            }
        });
        fileDialog.showDialog();
        
    }
    
    /**
     * Creates popup confirming choice to import all contacts from the android stock app
     */
    private void importContactsFromAndroidStockApp(){

    	final ATask task = new ATask(this, this);
    	
    	new AlertDialog.Builder(this)
	    .setTitle("Import Contacts")
	    .setMessage("Do you want to import your contacts from the stock Android application?")
	    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int which) { 
	            task.execute();
	        	resetContactsView();
	        }
	     })
	    .setNegativeButton("No", new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int which) { 
	            // do nothing
	        }
	     })
	     .show();
    	
    }
    
    
    
    private void showGroups(){
    	Intent i = new Intent(this, View_Groups.class);
    	startActivity(i);
    }
    
    private void about(){
    	new AlertDialog.Builder(this)
	    .setTitle("Contact Manager v1.0")
	    .setMessage("Project Members:\nAndrew P.\nMark C.\nNathaniel N.\nTyler B.\n\nCS5103 Fall 2013")
	    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int which) {
	        }
	     })
	     .show();
    }
    
    private void exit(){
    	onBackPressed();
    }
    
    

	@Override
	public void onTaskComplete() {
		resetContactsView();
	}
	
	//http://ahmadhashem.wordpress.com/2012/01/27/how-to-handle-incoming-calls-in-android-all-framework-versions/
	//I'm sure this isn't what the specifications are looking for. It's a temporary hack
	private void listenForPhone(){
		PhoneStateListener myCallListener = new PhoneStateListener(){
			@Override
			public void onCallStateChanged(int state, String incomingNumber) {
				// the variable incomingNumber holds the number calling.
				// the state variable holds the state of the phone (Ringing, Idle ...)
				switch (state) {
					case TelephonyManager.CALL_STATE_RINGING:
						// your logic here, right now the incoming caller is logged.
						Contact c = ContactManager.getContactByPhoneNumber(incomingNumber);
						Context context = getApplicationContext();
				        CharSequence text = "Unknown caller.";
				        int duration = Toast.LENGTH_SHORT;

				        
						if(c!=null){
							text = String.format("Incoming Call: ", c.getFirstName() + " " + c.getLastName() +" is calling you.");
						}
						
						Toast toast = Toast.makeText(context, text, duration);
				        toast.show();
							//Log.e("Incoming Call: ", c.getFirstName() + " " + c.getLastName() +" is calling you.");
						break;
					default:
						break;
				}
				super.onCallStateChanged(state, incomingNumber);
			}
		};
		TelephonyManager phoneManager = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
		phoneManager.listen(myCallListener, PhoneStateListener.LISTEN_CALL_STATE);
	}
	
	
	

    /** Inner class for implementing progress bar before fetching data **/
    private class ATask extends AsyncTask<Void, Void, Integer> 
    {
        private ProgressDialog dialog;
        private Activity context;
        private OnTaskCompleted listener;
        
        public ATask(Activity context, OnTaskCompleted listener){
        	dialog = new ProgressDialog(context);
        	this.context = context;
        	this.listener = listener;
        	
        }
        
        @Override
        protected void onPreExecute()
        {
            dialog.setMessage("Importing Contacts...");
            dialog.show();
        }

        @Override
        protected Integer doInBackground(Void... params) 
        {
        	ContactManager.importContactsFromAndroidStockApp(context);
            return 0;
        }

        @Override
        protected void onPostExecute(Integer result)
        {
            dialog.dismiss();

        	listener.onTaskComplete();
        	
            CharSequence text = "Contacts Imported.";
        	int duration = Toast.LENGTH_SHORT;

        	Toast toast = Toast.makeText(context, text, duration);
        	toast.show();
        }
    }
    

}


